/*
 * Copyright (c) 2011 Norbert Kopcsek
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.modulr.service {

	import mx.collections.IList;
	import mx.core.IMXMLObject;
	import mx.events.CollectionEvent;
	import mx.events.CollectionEventKind;

	import org.modulr.bundle.IBundleContext;

	/**
	 * The Injector extends the application according to the service references
	 * registered to the service tracker (managed by the Extender).
	 *
	 * @author Norbert Kopcsek
	 */
	public class Injector implements IMXMLObject {


		//------------------------------------------------------------------------------
		//
		//   Constructor 
		//
		//------------------------------------------------------------------------------

		public function Injector( context:IBundleContext = null, serviceName:String = null, serviceFilter:Object = null ) {
			super();

			serviceTracker = new ServiceTracker();
			serviceTracker.addEventListener( CollectionEvent.COLLECTION_CHANGE, handleChange );

			this.context = context;
			this.serviceName = serviceName;
			this.serviceFilter = serviceFilter;

		}


		//------------------------------------------------------------------------------
		//
		//   Properties (Getter/Setter) 
		//
		//------------------------------------------------------------------------------

		//--------------------------------------
		// context 
		//--------------------------------------

		/**
		 * The bundle context the service is registered for.
		 */
		[Bindable]
		public function get context():IBundleContext {
			return serviceTracker.context;
		}

		public function set context( value:IBundleContext ):void {
			if ( value == serviceTracker.context ) {
				return;
			}
			serviceTracker.context = value;
		}

		//--------------------------------------
		// serviceName 
		//--------------------------------------

		/**
		 * The name of the service managed by this Extender.
		 */
		[Bindable]
		public function get serviceName():String {
			return serviceTracker.serviceName;
		}

		public function set serviceName( value:String ):void {
			if ( value == serviceTracker.serviceName ) {
				return;
			}
			serviceTracker.serviceName = value;
		}

		//--------------------------------------
		// serviceFilter 
		//--------------------------------------

		/**
		 * The name of the service managed by this Extender.
		 */
		[Bindable]
		public function get serviceFilter():Object {
			return serviceTracker.serviceFilter;
		}

		public function set serviceFilter( value:Object ):void {
			if ( value == serviceTracker.serviceFilter ) {
				return;
			}
			serviceTracker.serviceFilter = value;
		}


		//------------------------------------------------------------------------------
		//
		//   Protected fields 
		//
		//------------------------------------------------------------------------------

		/**
		 * @private
		 * The service tracker managed by this Extender.
		 */
		protected var serviceTracker:ServiceTracker;


		//------------------------------------------------------------------------------
		//
		//  Methods 
		//
		//------------------------------------------------------------------------------

		/**
		 * Initalizes the injector by adding all services.
		 */
		public function initialize():void {
			installAllServiceReferences( serviceTracker );
		}

		/**
		 * Is implemetation of IMXMLObject;
		 * @includeDoc
		 */
		public function initialized( document:Object, id:String ):void {
		}


		//------------------------------------------------------------------------------
		//
		//   Protected methods 
		//
		//------------------------------------------------------------------------------

		/**
		 * @private
		 * Handles collection events of the service tracker.
		 */
		protected function handleChange( event:CollectionEvent ):void {
			switch ( event.kind ) {
				case CollectionEventKind.ADD:  {
					for each ( var serviceReferenceToBeAdded:IServiceReference in event.items ) {
						installServiceReference( serviceReferenceToBeAdded );
					}
					break;
				}
				case CollectionEventKind.REMOVE:  {
					for each ( var serviceReferenceToBeRemoved:IServiceReference in event.items ) {
						uninstallServiceReference( serviceReferenceToBeRemoved );
					}
					break;
				}
				default:  {
					return;
				}
			}
		}

		/**
		 * @private
		 * Adds all service references in the given IList.
		 */
		protected function installAllServiceReferences( serviceReferences:IList ):void {
			for ( var i:int = 0; i < serviceReferences.length; i++ ) {
				installServiceReference( serviceReferences.getItemAt( i ) as IServiceReference );
			}
		}

		/**
		 * @private
		 * Removes all service references in the given IList.
		 */
		protected function uninstallAllServiceReferences( serviceReferences:IList ):void {
			for ( var i:int = 0; i < serviceReferences.length; i++ ) {
				uninstallServiceReference( serviceReferences.getItemAt( i ) as IServiceReference );
			}
		}

		/**
		 * @private
		 * Adds a service reference.
		 */
		protected function installServiceReference( serviceReferences:IServiceReference ):void {
		}

		/**
		 * @private
		 * Removes a service reference.
		 */
		protected function uninstallServiceReference( serviceReferences:IServiceReference ):void {
		}
	}
}

